﻿using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using Engine;
using Microsoft.Xna.Framework;
using ThinkDotNetBotApiCommon.Ammos;

namespace ThinkDotNetEngine.Bots.Ammos
{
    public class AmmoHandler : IAmmoHandler
    {
        private readonly World World;

        public AmmoHandler(World world)
        {
            World = world;
            _launchedAmmos = new ObservableCollection<IAmmoBase>();
            _launchedAmmos.CollectionChanged += LaunchedAmmosCollectionChanged;
        }

        #region Properties

        private readonly ObservableCollection<IAmmoBase> _launchedAmmos;

        public IAmmoBase[] LaunchedAmmos
        {
            get { return _launchedAmmos.ToArray(); }
        }

        #endregion

        #region Methods

        public GameTime AddAmmo(IAmmoBase ammoBase)
        {
            _launchedAmmos.Add(ammoBase);
            return _gameTime;
        }
        public bool CanBeLaunched(double lastLaunchTime, double launchTime)
        {           
            return _gameTime.TotalGameTime.TotalMilliseconds - lastLaunchTime > launchTime;
        }        
        public void Update(GameTime gameTime,AmmoBase ammoBase,out bool isRemoved)
        {
            isRemoved = false;
            ammoBase.Update(gameTime);
            
            CheckIfHit(ammoBase, ref isRemoved);
            CheckIfExpired(ammoBase, ref isRemoved);          
        }
     
        public void UpdateAll(GameTime gameTime)
        {
            _gameTime = gameTime;
            for (int i = 0; i < _launchedAmmos.Count;i++ )
            {
                bool isRemoved;
                Update(gameTime, (AmmoBase)_launchedAmmos[i], out isRemoved);
                if (isRemoved)
                    i--;
            }
        }

        #endregion

        #region Private Methods

        private void CheckIfHit(AmmoBase ammoBase, ref bool isRemoved)
        {
            object collidedObject = World.DetectCollision(ammoBase.CurrentPosition);
            if (collidedObject != null)
            {
                if (collidedObject is TankBot)
                {
                    var tankBot = (TankBot)collidedObject;
                    if (ammoBase.Weapon.Owner != tankBot)
                        tankBot.Hit(ammoBase);
                    else
                        return;
                }
                _launchedAmmos.Remove(ammoBase);
                isRemoved = true;
            }
        }
        private void CheckIfExpired(AmmoBase ammoBase, ref bool isRemoved)
        {
            if (ammoBase.CurrentDuration > ammoBase.MaxDuration)
            {
                _launchedAmmos.Remove(ammoBase);
                isRemoved = true;
            }
        }

        #endregion

        #region Events

        public event NotifyCollectionChangedEventHandler AmmosCollectionChanged = delegate { };

        private void LaunchedAmmosCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            AmmosCollectionChanged(this, e);
        }

        #endregion

        #region Fields

        private GameTime _gameTime=new GameTime();

        #endregion
    }
}
